use std::fs;

use tree_sitter::{Parser, TreeCursor};
use walkdir::WalkDir;

pub fn by_class_name_and_method(
    project_path: &str,
    class_name: &str,
    method_name: Option<&String>,
) -> Vec<String> {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    let cans = find_by_class_name_and_method(project_path, class_name, method_name);

    // 合并为字符串
    return cans
        .into_iter()
        .map(|item| {
            return format!("{}\n{}", item.import.join("\n"), item.code.join("\n"));
        })
        .collect();
}

pub struct ClassAndNameResult {
    import: Vec<String>,
    code: Vec<String>,
}

// 根据类名+方法名，结构化返回相关的代码
pub fn find_by_class_name_and_method(
    project_path: &str,
    class_name: &str,
    method_name: Option<&String>,
) -> Vec<ClassAndNameResult> {
    // java 解析器
    let mut parser = Parser::new();
    parser
        .set_language(&tree_sitter_java::LANGUAGE.into())
        .expect("tree_sitter_sequel init fail");

    let contents: Vec<ClassAndNameResult> = WalkDir::new(project_path)
        .sort_by_file_name()
        .follow_links(true)
        .into_iter()
        .filter_map(|entry| {
            if let Ok(path) = entry {
                let full_path: String = path.path().display().to_string();
                if full_path.ends_with(".java") {
                    if let Ok(file_content) = fs::read_to_string(&full_path) {
                        // 解析
                        let node_tree = parser.parse(file_content.as_str(), None).unwrap();

                        // 查找package
                        let mut node_cursor = node_tree.walk();
                        if let Some(package_name) =
                            super::base::get_package_name(&mut node_cursor, &file_content)
                        {
                            let package_with_dot = format!("{}.", package_name);
                            if class_name.starts_with(&package_with_dot) {
                                // 当前文件可能有指定类
                                // 截取类名
                                if let Some(class_name_short) =
                                    class_name.strip_prefix(&package_with_dot)
                                {
                                    if let Some(class_content) = get_class_by_name(
                                        &class_name_short,
                                        &mut node_cursor,
                                        &file_content,
                                    ) {
                                        // 返回的结构是 import + 代码块
                                        // 查找imports
                                        let imports = super::base::get_import(
                                            &mut node_tree.walk(),
                                            &file_content,
                                        );

                                        // 查找指定方法
                                        if let Some(method_name) = &method_name {
                                            let method_content = get_method_by_name(
                                                method_name,
                                                &mut node_cursor,
                                                &file_content,
                                            );
                                            return Some(ClassAndNameResult {
                                                import: imports,
                                                code: method_content,
                                            });
                                        } else {
                                            return Some(ClassAndNameResult {
                                                import: imports,
                                                code: vec![class_content],
                                            });
                                        }
                                    }
                                }
                            }
                        }

                        return None;
                    }
                }
            }
            return None;
        })
        .collect();
    return contents;
}

pub fn get_class_by_name(
    class_name: &str,
    node_cursor: &mut TreeCursor,
    source_code: &str,
) -> Option<String> {
    loop {
        let current_node = node_cursor.node();
        if current_node.kind() == "class"
            || current_node.kind() == "enum"
            || current_node.kind() == "interface"
        {
            let class_class = &source_code[current_node.start_byte()..current_node.end_byte()];
            // 移动到兄弟节点 className
            if node_cursor.goto_next_sibling() {
                let class_name_node = node_cursor.node();
                if class_name_node.kind() == "identifier" {
                    let node_class_name =
                        &source_code[class_name_node.start_byte()..class_name_node.end_byte()];

                    if class_name == node_class_name {
                        let mut class_content = vec![class_class, node_class_name];

                        loop {
                            // 继承 实现 类详情 ;
                            node_cursor.goto_next_sibling();
                            let now_node = node_cursor.node();
                            let now_node_content =
                                &source_code[now_node.start_byte()..now_node.end_byte()];
                            class_content.push(now_node_content);

                            if now_node.kind() == "class_body"
                                || now_node.kind() == "enum_body"
                                || now_node.kind() == "interface_body"
                            {
                                break;
                            }
                        }

                        // 找到指定class
                        return Some(class_content.join(" "));
                    }
                }
            }

            // 一个文件只有一个packgeName
            return None;
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            if !node_cursor.goto_parent() {
                return None;
            }
        }
    }
}

pub fn get_method_by_name(
    method_name: &str,
    node_cursor: &mut TreeCursor,
    source_code: &str,
) -> Vec<String> {
    let root_node = node_cursor.node();
    let mut methods: Vec<String> = vec![];
    loop {
        let current_node = node_cursor.node();
        if current_node.kind() == "formal_parameters" {
            // 逆向寻找 方法名,返回值
            node_cursor.goto_previous_sibling();
            node_cursor.goto_previous_sibling();

            // 返回值
            let return_type_node = node_cursor.node();
            let return_type =
                &source_code[return_type_node.start_byte()..return_type_node.end_byte()];

            // 方法名
            node_cursor.goto_next_sibling();
            let method_name_node = node_cursor.node();
            let now_method_name =
                &source_code[method_name_node.start_byte()..method_name_node.end_byte()];

            if now_method_name == method_name {
                // 找到指定方法
                let mut method_content = vec![return_type, now_method_name];

                loop {
                    // 参数 异常 方法体 ;
                    node_cursor.goto_next_sibling();
                    let now_node = node_cursor.node();
                    let now_node_content = &source_code[now_node.start_byte()..now_node.end_byte()];
                    method_content.push(now_node_content);

                    if now_node.kind() == "block" || now_node.kind() == ";" {
                        break;
                    }
                }

                // 保存
                methods.push(method_content.join(" "));

                // 进入下一个节点
                node_cursor.goto_next_sibling();
            } else {
                // 方法名不匹配，回到 formal_parameters
                node_cursor.goto_next_sibling();
            }
        }

        if node_cursor.goto_first_child() {
            continue;
        }

        loop {
            if node_cursor.goto_next_sibling() {
                break;
            }

            node_cursor.goto_parent();
            if root_node == node_cursor.node() {
                return methods;
            }
        }
    }
}
